// node.cpp
//

#include "node.hpp"
#include "model.hpp"
#include "renderer.hpp"



// global none data
static NDataNone N_DATA_NONE{};



// Node::Node
//
Node::Node ( NodeData &data,
             Node *parent )
  : data(data)
{
  if (parent)
    parent->add_child(*this);
}



// Node::Node
//
Node::Node ( Node *parent )
  : Node(N_DATA_NONE, parent)
{
}



// Node::~Node
//
Node::~Node ()
{
  while (children)
    remove_child(*children);
}



// Node::set_data
//
void Node::set_data ( NodeData &data )
{
  this->data = data;
}



// Node::add_child
//
void Node::add_child ( Node &child )
{
  GLT_ASSERT(!child.parent);
  GLT_ASSERT(!child.prev);
  GLT_ASSERT(!child.next);

  child.parent = this;
  if (children)
    {
      children_tail->next = &child;
      child.prev = children_tail;
      children_tail = &child;
    }
  else
    {
      children = children_tail = &child;
    }
}



// Node::remove_child
//
void Node::remove_child ( Node &child )
{
  GLT_ASSERT(child.parent == this);

  if (child.prev)
    child.prev->next = child.next;
  if (child.next)
    child.next->prev = child.prev;
  
  if (children == &child)
    children = child.next;
  if (children_tail == &child)
      children_tail = child.prev;

  child.parent = child.next = child.prev = nullptr;
}



// NDataScene::render_prepare
//
void NDataScene::render_prepare ( SceneView &scene_view )
{
  // [TODO]
}



// NDataScene::render
//
void NDataScene::render ( RenderContext &rc )
{
  // GLT_TRACE("data scene render");
}



// NDataLight::render_prepare
//
void NDataLight::render_prepare ( SceneView &scene_view )
{
  // [TODO]
}



// NDataLight::render
//
void NDataLight::render ( RenderContext &rc )
{
  rc.set_light(wgl_light);
}



// NDataEntity::NDataEntity
//
NDataEntity::NDataEntity ( Model &model,
                           wgl::Material &material,
                           Texture &texture,
                           EntityGroup group )
  : model(model),
    material(&material),
    texture(&texture),
    group(group)
{
}




// NDataEntity::render_prepare
//
void NDataEntity::render_prepare ( SceneView &scene_view )
{
  // [TODO]
}



// NDataEntity::NDataEntity
//
NDataEntity::NDataEntity ( Model &model,
                           EntityGroup group )
  : model(model),
    texture(nullptr),
    group(group)
{
}



// render
//
void NDataEntity::render ( RenderContext &rc )
{
  // GLT_TRACE("data entity render");

  if (!visible)
    return;
  
  model.upload();

  rc.set_render_group(group);
  rc.set_model_matrix(transfo.get_matrix());
  rc.set_material(material);
  if (rc.is_textured() && texture)
    texture->bind();
  model.buffer.render();
}
